<?php

namespace App\Redis;


use App\Common\Log;
use App\Traits\TraitCommon;
use App\Traits\TraitConnectDB;
use App\X\EHelper;
use XWX\Common\H;
use XWX\Common\Traits\TraitIns;

/**
 * redis 订阅事件
 *
 * Class SubscribeEvent
 * @package App\Redis
 */
class SubscribeEvent
{
    use TraitConnectDB, TraitCommon, TraitIns;

    public $pub_db = '3';//默认监听db


    /**
     * @return \App\Common\DB\CommonRedis
     * @throws \Exception
     */
    public function getRedis()
    {
//        $this->redis6380()->select($this->pub_db);

        return $this->redis6380();
    }


    public function funcEventExpired()
    {
        //监听指定db的key过期事件
        if ($this->getRedis()->pSubscribe(["__keyevent@{$this->pub_db}__:expired"]))
        {
            while ($msg = $this->getRedis()->recv())
            {
                // msg是一个数组, 包含以下信息
                // $type # 返回值的类型：显示订阅成功
                // $name # 订阅的频道名字 或 来源频道名字
                // $info  # 目前已订阅的频道数量 或 信息内容
                $type = $msg[0];

                if ($type == 'psubscribe')
                {
                    // 频道订阅成功消息，订阅几个频道就有几条
                    Log::funcLogInfo(__METHOD__, "订阅开启:{$this->pub_db}");
                }
                else if ($type == 'pmessage')
                {
                    $r = $this->funcMessage($msg);
                    Log::funcLogDebug(__METHOD__, H::funcToStr($r));
                    if ($r->errcode == 55)
                    {
                        Log::funcLogInfo(__METHOD__, '订阅关闭');
                        break;
                    }
                }
            }
        };
    }


    /**
     * 关闭监听key过期事件
     *
     * @throws \Exception
     */
    public function funcEventExpiredClose()
    {
        $this->getRedis()->setEx('close', 1, '');
    }


    private function funcMessage($msg)
    {
        Log::funcLogDebug(__METHOD__, $msg);

        if (!H::funcStrContains($msg[1], 'expired'))
        {
            return $this->funcGetR(-1052, 'not event');
        }

        if (count($msg) < 4)
        {
            return $this->funcGetR(-1057, '参数异常');
        }


        $key = $msg[3];
        if ($key == 'close')
        {
            return $this->funcGetR(55, '订阅关闭');
        }


        //access_token|x
        $data = explode('|', $key);
        $class_name = $data[0];
        $val = '';
        if (count($data) > 1)
        {
            $val = $data[1];
        }


        $class = sprintf('App\Redis\expired\%s', $class_name);
        Log::funcLogDebug(__METHOD__, $class);
        if (class_exists($class))
        {
            EHelper::funcGo(function () use ($class, $val)
            {
                try
                {
                    $app = new $class();
                    $app->funcHandle($val);
                }
                catch (\Exception $ex)
                {
                    Log::funcLogErr(__METHOD__, $ex->getMessage());
                }
            });
        }


        return $this->funcGetR(0);
    }
}